<?php


namespace app\elasticquent;

use App\SearchBuilders\ProductSearchBuilder;
use Elasticsearch\ClientBuilder;
use Elasticsearch\Client;

class Elastic
{
    protected $collection;

    protected $es;

    public $indexName;

    public $typeName = '_doc';

    public $aliasName;

    protected $settings;

    protected $mappings;

    protected $params;

    /**
     * @desc 构建客户端
     */
    public function __construct()
    {
        $config = config('elasticsearch.connections');
        $host = $config[$this->collection]['host'];
        $this->es = ClientBuilder::create()->setHosts([$host])->build();
    }

    public function initParams()
    {
        $this->params = [
            'index' => $this->indexName,
            'type' => $this->typeName,
            'body' => [
                'query' => [

                ],
            ],
        ];
    }


    /**
     * @desc 创建索引
     */
    public function createIndex()
    {
        $params = [
            'index' => $this->indexName,
            'body' => [
                'settings' => $this->settings,
                'mappings' => $this->mappings,
                'aliases' => [
                    $this->aliasName => new \stdClass(),
                ],
            ]
        ];

        $this->es->indices()->create($params);

    }

    /**
     * @desc 检查索引是否存在
     */
    public function exists()
    {
         return $this->es->indices()->exists(['index'=>$this->indexName]);
    }

    /**
     * @desc 删除索引
     */
    public function deleteIndex(){
        return $this->es->delete($this->indexName);
    }

    /**
     * @desc 单个索引文档
     * @param array $data 文档数据 如 ['field1'=>'value1', 'field2'=>'value2']
     * @param string $idKey 创建id值 不传es自动创建 如：field1
     */
    public function singleDoc(array $data =[])
    {
        try{
            $params = [
                'index' => $this->indexName,
                'type' =>  $this->typeName,
            ];
            if (!$data) return false;
            if (isset($data['doc_id'])){
                $params['id'] = $data['doc_id'];
                unset($data['doc_id']);
            }

            $params['body'] = $data;

            $res = $this->es->index($params);
        }catch(\Exception $e){
            throw $e;
        }
        if (!isset($res['_shards']['successful']) || !$res['_shards']['successful']){
            return false;
        }
        return true;
    }

    /**
     * @desc 批量索引文档
     * @param array $data 文档数据 如 ['field1'=>'value1', 'field2'=>'value2']
     * @param string $idKey 创建id值 不传es自动创建 如：field1
     */
    public function bulkDoc($docs=[])
    {
        if (!$docs) return false;

        try{
            $params['body'] = [];
            $params['index'] = $this->indexName;
            $params['type'] = $this->typeName;
            foreach($docs as $key => $doc){
                $params['body'][] = [
                    'index' => [
                        '_id' => isset($doc['doc_id']) ? $doc['doc_id'] : null
                    ]
                ];
                if(isset($doc['doc_id']))  unset($doc['doc_id']);

                $params['body'][] = $doc;
                if ($key+1 % 1000 == 0) {
                    $this->es->bulk($params);
                    $params['body'] = [];
                }
            }
            if (!empty($params['body'])) {
                $this->es->bulk($params);
            }
        }catch(\Exception $e){
            throw $e;
        }
    }

    //单词条完全匹配查询 $fileds = ['keyworde' => 'abc']
    public function term($fileds=[])
    {
        $this->params['body']['query']['term'] = $fileds;
        return $this;
    }

    //多次条查询 匹配其中任意一个,就匹配查询条件 $fileds = ['keyworde' => ['abc','acb']]
    public function terms($fileds=[])
    {
        $this->params['body']['query']['terms'] = $fileds;
        return $this;
    }

    public function match($fileds=[])
    {
        $this->params['body']['query']['match'] = $fileds;
        return $this;
    }

    public function match_all()
    {
        $this->params['body']['query']['match_all'] = [];
        return $this;
    }

    //前缀匹配
    public function prefix($fileds=[])
    {

    }

    //通配符匹配
    public function wildcard($fileds=[])
    {

    }

    //正则表达式
    public function regexp($fileds=[])
    {

    }

    //短语匹配 必须匹配短语中的所有分词，并且保证各个分词的相对位置不变
    public function match_phrase($fileds=[])
    {

    }

    public function match_phrase_prefix($fileds=[])
    {

    }

    public function multi_match($fileds=[])
    {

    }

    //bool 查询 must should must_not filter
    public function must($fileds=[])
    {
        if($fileds){
            $this->params['body']['query']['bool']['must'] = [];
            foreach($fileds as $filed => $value){
                $this->params['body']['query']['bool']['must'][] = [
                    'match' => [$filed => $value]
                ];
            }
        }

        return $this;
    }

    public function filter($fileds=[])
    {
        if($fileds){
            $this->params['body']['query']['bool']['filter'] = [];
            foreach($fileds as $filed => $value){
                $this->params['body']['query']['bool']['filter'][] = [
                    'term' => [$filed => $value]
                ];
            }
        }

        return $this;
    }

    public function paginate($page=1,$size=10)
    {
        $this->params['body']['from'] = ($page - 1) * $size;
        $this->params['body']['size'] = $size;
        return $this;
    }

    public function orderBy($field, $direction)
    {
        if (!isset($this->params['body']['sort']))
        {
            $this->params['body']['sort'] = [];
        }
        $this->params['body']['sort'][] = [$field => $direction];

        return $this;
    }

    public function search()
    {
        try {
            $response = $this->es->search($this->params);

            $res['total'] = $response['hits']['total']['value'];
            $res['data'] = $response['hits']['hits'];

        }catch(\Exception $e){
            throw $e;
        }
        return $res;
    }

}